package com.qs.zk.utils;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

/**
 * 自定义类，完成zookeeper服务连接，获取zookeeper对象
 *
 * @author qinyupeng
 * @since 2019-03-14 16:12:51
 */
public class ZkConnection {

    private CountDownLatch countDownLatch = new CountDownLatch(1);

    //包含zk服务器信息字符串（包括集群字符串）
    private String connectString;

    //连接超时时间
    private int timeout;

    private ZooKeeper zooKeeper;


    public ZkConnection(String connectString, int timeout) {
        this.connectString = connectString;
        this.timeout = timeout;
    }


    public ZooKeeper getZooKeeper() {
        return zooKeeper;
    }

    public String getConnectString() {
        return connectString;
    }

    public void setConnectString(String connectString) {
        this.connectString = connectString;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public ZooKeeper connect() throws IOException, InterruptedException {
        zooKeeper = new ZooKeeper(connectString, timeout, new Watcher() {
            /**
             * 首先要明白：
             * 1、回调都是异步实现的，也就是说执行process()方法不是main线程；
             * 2、zookeeper成功获取连接时提供event.getState()="CONNECTED"（中间会存在CONNECTING状态）；
             * 3、注意countDownLatch使用的目的：只有成功连接后，该方法返回zookeeper实例；
             */
            @Override
            public void process(WatchedEvent event) {
                if (Event.KeeperState.SyncConnected.equals(event.getState())) {
                    countDownLatch.countDown();
                }
            }
        });

        //使用countDownLatch，main线程执行到这里时候开始等待，等到其他线程调用countDownLatch.countDown()方法，将计数-1
        countDownLatch.await();
        return zooKeeper;
    }


    /**
     * 测试：获取Zookeeper对象
     */
    public static void main(String[] args) throws IOException, InterruptedException {
        //注意：3个服务器集群后，连接字符串为：ip:port,ip:port
        String connectString = "172.16.109.130:2181,172.16.109.131:2181,172.16.109.132:2181";
        ZkConnection zkConnection = new ZkConnection(connectString, 20000);
        ZooKeeper connect = zkConnection.connect();
        System.out.println("--->>>connect=" + connect);
    }
}
